package java基础知识;

import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author coderFu
 * @create 2022/3/4
 * jdk8 中 stream 流的使用
 */
public class JDK8Stream {

    public static void main(String[] args) {

        List<Student2> student2List = new ArrayList<>();

        int count = 0;
        // 计算学生中来自成都的数量
        for (Student2 student : student2List){
            if ("chendu".equals(student.getCity())){
                count ++;
            }
        }

        // 使用 Stream 流来处理
      //  student2List.stream().filter(student2 -> "chendu".equals(student2.getCity())).count();
        // stream 类的 多个工具函数，返回值都是 Stream ，所以可以不断调用
        // 工具方法，有责任链的影子

        List<Integer> list = new ArrayList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        list.add(5);
        list.add(3);
        List<Integer> collect = list.stream().distinct().collect(Collectors.toList());
        System.out.println("去重后的集合元素为："+collect);



        Student2 student2 = new Student2("河南", Arrays.asList("1元","2元"));
        Student2 student3 = new Student2("北京", Arrays.asList("5元","2元"));
        Student2 student4 = new Student2("上海", Arrays.asList("8元","2元"));
        Student2 student5 = new Student2("北京", Arrays.asList("10元","5元"));


        student2List.add(student2);
        student2List.add(student3);
        student2List.add(student4);
        student2List.add(student5);
        System.out.println(student2List);

        //Stream<T> filter(Predicate<? super T> predicate):
        // predicate： 断言型接口， 所以filter方法中是接收一个
        // 和Predicate函数对应Lambda 表达式，返回一个布尔值，从流中过滤
        //某些元素


        // Stream<T> sorted(Comparator<? super T> comparator):
        // 指定比较规则进行排序  reversed 倒序返回

        student2List.stream()
                .sorted(Comparator.comparing(Student2::getCity))
                .forEach(student21 -> System.out.println(student21));

        //Stream<T> limit(long maxSize):
        // 截断流，使其元素不超过给定数量，如果元素的个数小于maxSize
        // 那就获取所有元素
        student2List.stream()
                .limit(3)
                .forEach(student21 -> System.out.println("限制元素的个数"+student21));



        student2List.stream()
                // 去重操作 根据 hashCode 和 equals 来去重
                .distinct()
                .forEach(student21 -> System.out.println(student21.getCity()));

        // Stream<T> skip(long n):
        // 跳过前N个元素，若不足N个 返回为空
        // 找到最小的城市

        student2List.stream()
                .sorted(Comparator.comparing(Student2::getCity).reversed())
                .skip(student2List.size()-1)
                .forEach(student21-> System.out.println("跳过前两个"+student21));


        //Stream<R> map(Function<? super T, ? extends R> mapper)：
        // 转换映射操作，将流中的每个元素转换为 其他的数据类型
        // mapToInt, mapToLong, mapToDouble 将一个Stream转换为一个
        // 新的 Stream

        collect.stream()
                .map(a->a.doubleValue())
                .forEach(System.out::println);

        student2List.stream()
                .map(student21 -> "欢迎123"+student21.getCity())
                .forEach(System.out::println);

        //Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)：
        // 接收一个Function函数作为参数，将流中的每个值都转换为另一个流，然后把所有流
        //流，flatMap 也有三个具体类型的方法，分别是： flatMapToInt flatMapToLong
        // flatMapToDouble

        student2List.stream()
                .map(student21 -> student21.getMoney())
                .forEach(System.out::println);

        // 合成一个流进行输出
        student2List.stream()
                .flatMap(student21 -> student21.getMoney().stream())
                .forEach(System.out::println);



        // 终端操作：
        // void forEach(Consumer<? super T> action): 输出信息
        collect.forEach(System.out::println);

        // <R, A> R collect(Collector<? super T, A, R> collector):
        // 收集、将流转化为其他形式，比如转化为list、Set、Map

        List<String> collect1 = student2List.stream().map(student21 -> student21.getCity()).collect(Collectors.toList());
        System.out.println(collect1);
        Set<String> collect2 = student2List.stream().map(student21 -> student21.getCity()).collect(Collectors.toSet());

        Map<String, Student2> collect3 = student2List.stream().collect(Collectors.toMap(Student2::getCity, Function.identity(), (K1, K2) -> K2));

        // Fork / join 框架 双端队列
        // 并行任务框架  将任务拆分为多个小任务， 每个小任务执行完的结果
        // 在合并成为一个结果，在任务的执行过程中使用工作窃取算法
        // work-stealing ，减少线程之间的竞争 从头尾进行任务分派执行。
        // 多个线程一起消费 双端队列 有点像策略模式

        // Stream 只有两种操作， 中间操作、 终端操作，中间操作只是一种标记
        // 只有终端操作才会实际触发执行，所以Stream大致是用某种方式记录
        // 中间操作，且每个流只能使用一次。

    }







}


class Student2 {

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student2 student2 = (Student2) o;
        return Objects.equals(city, student2.city);
    }

    @Override
    public int hashCode() {
        return Objects.hash(city);
    }

    public Student2() {

    }

    @Override
    public String toString() {
        return "Student2{" +
                "city='" + city + '\'' +
                '}';
    }

    public Student2(String city) {
        this.city = city;
    }

    String city;

    List<String> money;

    public Student2(String city, List<String> money) {
        this.city = city;
        this.money = money;
    }

    public List<String> getMoney() {
        return money;
    }

    public void setMoney(List<String> money) {
        this.money = money;
    }

    public String getCity() {
        return city;
    }

    public void setCity(String city) {
        this.city = city;
    }
}
